/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "PlanetWars2dRT-core/specific/model/player_playing_functions.h"
#include "PlanetWars2dRT-core/specific/model/ship_position.h"
#include "PlanetWars2dRT-core/specific/model/planet_position.h"
#include "PlanetWars2dRT-core/utils/collision_2d_uint.h"


EXTERN_C_BEGIN


size_t
universe_get_nb_planets_of_player_index(const universe_t* a_universe,
					unsigned char player_index)
{
  size_t nb_result = 0;
  const size_t nb_planets = universe_get_nb_planets(a_universe);
  for(size_t i=0; i < nb_planets; ++i)
    {
      if(universe_get_const_planet_no_check(a_universe, i)->player_index
	 == player_index)
	{
	  ++nb_result;
	}
    }
  return nb_result;
}

const planet_t**
universe_get_planets_of_player_index(const universe_t* a_universe,
				     unsigned char player_index,
				     size_t* nb)
{
  *nb = universe_get_nb_planets_of_player_index(a_universe, player_index);
  
  if(*nb == 0)
    {
      return NULL;
    }
  const planet_t** planets = (const planet_t**) malloc(*nb * sizeof(planet_t*));
  if(planets == NULL)
    {
      return NULL;
    }
  
  const size_t universe_nb_planets = universe_get_nb_planets(a_universe);
  for(size_t i=0, j=0;
      i < universe_nb_planets && j < *nb;
      ++i)
    {
      const planet_t* planet_i = universe_get_const_planet_no_check(a_universe, i);
      if(planet_i->player_index == player_index)
	{
	  planets[j++] = planet_i;
	}
    }
  
  return planets;
}

const planet_t**
universe_get_planets_not_of_player_index(const universe_t* a_universe,
					 unsigned char player_index,
					 size_t* nb)
{
  *nb = universe_get_nb_planets_not_of_player_index(a_universe, player_index);
  
  if(*nb == 0)
    {
      return NULL;
    }
  const planet_t** planets = (const planet_t**) malloc(*nb * sizeof(planet_t*));
  if(planets == NULL)
    {
      return NULL;
    }
  
  const size_t universe_nb_planets = universe_get_nb_planets(a_universe);
  for(size_t i=0, j=0;
      i < universe_nb_planets && j < *nb;
      ++i)
    {
      const planet_t* planet_i = universe_get_const_planet_no_check(a_universe, i);
      if(planet_i->player_index != player_index)
	{
	  planets[j++] = planet_i;
	}
    }
  
  return planets;
}

position_2d_uint*
universe_get_center_positions_of_planets_not_of_player_index(const universe_t* universe,
							     unsigned char player_index,
							     size_t* nb)
{
  *nb = universe_get_nb_planets_not_of_player_index(universe, player_index);
  
  if(*nb == 0)
    {
      return NULL;
    }
  position_2d_uint* positions = (position_2d_uint*) malloc(*nb *
							   sizeof(position_2d_uint));
  if(positions == NULL)
    {
      return NULL;
    }
  
  const size_t universe_nb_planets = universe_get_nb_planets(universe);
  for(size_t i=0, j=0;
      i < universe_nb_planets && j < *nb;
      ++i)
    {
      const planet_t* planet_i = universe_get_const_planet_no_check(universe, i);
      if(planet_i->player_index != player_index)
	{
	  positions[j++] = planet_get_center_position(planet_i);
	}
    }
  
  return positions;
}

position_2d_uint
universe_get_center_position_of_planets_of_player_index(const universe_t* universe,
							unsigned char player_index)
{
  position_2d_uint position;
  position.x = 0;
  position.y = 0;
  size_t nb_result = 0;
  
  const size_t nb_planets = universe_get_nb_planets(universe);
  for(size_t i=0; i < nb_planets; ++i)
    {
      const planet_t* planet_i = universe_get_const_planet_no_check(universe, i);
      if(planet_i->player_index == player_index)
	{
	  position.x += planet_get_center_position_x(planet_i);
	  position.y += planet_get_center_position_y(planet_i);
	  ++nb_result;
	}
    }
  
  if(nb_result > 0)
    {
      position.x /= nb_result;
      position.y /= nb_result;
    }
  return position;
}

position_2d_uint
universe_get_center_position_of_planets_not_of_player_index(const universe_t* universe,
							    unsigned char player_index)
{
  position_2d_uint position;
  position.x = 0;
  position.y = 0;
  size_t nb_result = 0;
  
  const size_t nb_planets = universe_get_nb_planets(universe);
  for(size_t i=0; i < nb_planets; ++i)
    {
      const planet_t* planet_i = universe_get_const_planet_no_check(universe, i);
      if(planet_i->player_index != player_index)
	{
	  position.x += planet_get_center_position_x(planet_i);
	  position.y += planet_get_center_position_y(planet_i);
	  ++nb_result;
	}
    }
  
  if(nb_result > 0)
    {
      position.x /= nb_result;
      position.y /= nb_result;
    }
  return position;
}


size_t
universe_get_nb_ships_of_player_index(const universe_t* a_universe,
				      unsigned char player_index)
{
  size_t nb_result = 0;
  const size_t nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0; i < nb_ships; ++i)
    {
      if(universe_get_const_ship_no_check(a_universe, i)->player_index
	 == player_index)
	{
	  ++nb_result;
	}
    }
  return nb_result;
}

ship_t**
universe_get_ships_of_player_index(universe_t* a_universe,
				   unsigned char player_index,
				   size_t* nb)
{
  *nb = universe_get_nb_ships_of_player_index(a_universe, player_index);
  
  if(*nb == 0)
    {
      return NULL;
    }
  ship_t** ships = (ship_t**) malloc(*nb * sizeof(ship_t*));
  if(ships == NULL)
    {
      return NULL;
    }
  
  const size_t universe_nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0, j=0;
      i < universe_nb_ships && j < *nb;
      ++i)
    {
      ship_t* ship_i = universe_get_ship_no_check(a_universe, i);
      if(ship_i->player_index == player_index)
	{
	  ships[j++] = ship_i;
	}
    }
  
  return ships;
}

ship_t**
universe_get_ships_not_of_player_index(universe_t* a_universe,
				       unsigned char player_index,
				       size_t* nb)
{
  *nb = universe_get_nb_ships_not_of_player_index(a_universe, player_index);
  
  if(*nb == 0)
    {
      return NULL;
    }
  ship_t** ships = (ship_t**) malloc(*nb * sizeof(ship_t*));
  if(ships == NULL)
    {
      return NULL;
    }
  
  const size_t universe_nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0, j=0;
      i < universe_nb_ships && j < *nb;
      ++i)
    {
      ship_t* ship_i = universe_get_ship_no_check(a_universe, i);
      if(ship_i->player_index != player_index)
	{
	  ships[j++] = ship_i;
	}
    }
  
  return ships;
}

size_t
universe_ships_of_player_index_go_to(universe_t* a_universe,
				     unsigned char player_index,
				     const position_2d_uint* position_to_go)
{
  size_t nb_moved = 0;
  const size_t nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0; i < nb_ships; ++i)
    {
      ship_t* ship_i = universe_get_ship_no_check(a_universe, i);
      if(ship_i->player_index == player_index)
	{
	  ship_i->position_to_go = *position_to_go;
	  ++nb_moved;
	}
    }
  return nb_moved;
}

size_t
universe_get_nb_ships_of_player_index_in_rectangle(const universe_t* a_universe,
						   unsigned char player_index,
						   const position_2d_uint* pos,
						   const size_2d_uint* size)
{
  size_t nb = 0;
  const size_t universe_nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0; i < universe_nb_ships; ++i)
    {
      const ship_t* ship_i = universe_get_const_ship_no_check(a_universe, i);
      const position_2d_uint ship_i_pos =
	ship_get_top_left_position_current(ship_i);
      if(ship_i->player_index == player_index &&
	 is_rectangle_in_rectangle_2d_uint(pos,  &ship_i_pos,
					   size, &ship_i->size))
	{
	  ++nb;
	}
    }
  return nb;
}

vector_ship_ptr
universe_get_vector_ships_of_player_index_in_rectangle(universe_t* a_universe,
						       unsigned char player_index,
						       const position_2d_uint* pos,
						       const size_2d_uint* size)
{
  vector_ship_ptr ships;
  VECTOR_GENERIC_STATIC_INIT_FIRST_TIME_ONLY(&ships, 0, ship_ptr);
  
  const size_t universe_nb_ships = universe_get_nb_ships(a_universe);
  for(size_t i=0; i < universe_nb_ships; ++i)
    {
      ship_t* ship_i = universe_get_ship_no_check(a_universe, i);
      const position_2d_uint ship_i_pos =
	ship_get_top_left_position_current(ship_i);
      if(ship_i->player_index == player_index &&
	 is_rectangle_in_rectangle_2d_uint(pos,  &ship_i_pos,
					   size, &ship_i->size))
	{
	  VECTOR_GENERIC_STATIC_PUSH_BACK(&ships, ship_i, ship_ptr);
	}
    }
  
  return ships;
}


EXTERN_C_END
